跳到主要内容

SpringCloud 基础概念:导航

微服务项目:谷粒商城项目文档

RPC 是什么

就是远距离调用(Remote Procedure Call)==> 分布式系统间通信

那 RPC 框架的作用是什么呢?主要是处理下面两块

1、解决分布式系统中,服务之间的调用问题。 2、远程调用时,要能够像本地调用一样方便,让调用者感知不到远程调用的逻辑。

RPC 和 HTTP 是一个并行的概念?

看网上很多回答把这两种都描述成一个层面的东西,看的一脸懵逼

image.png

红框开始就是 RPC,可见其实 RPC 是一整套实现框架而非某种协议,不管 HTTP 还是 TCP 都只是一种通信方式(注意不一定要实现图片上的功能,只是一般的 RPC 框架都有这些功能)

按照基于的网络协议,RPC 可以分为:

基于 HTTP 的 RPC:例如基于文本的SOAP(XML)、Rest 风格(JSON),基于二进制Hessian(Binary)

基于 TCP 的 RPC(通常会借助 Mina、Netty 等高性能网络框架)

注意: 网上很多回答把 Restful 风格的请求和 RPC 区分开来,这是不对的,因为 Restful 只是 RPC 的一种实现方式,他们可能想表达旧时的 RPC 用的 TCP 方式传输

按照数据形式,RPC分为:

基于XML的RPC 基于JSON的RPC 基于二进制的RPC

SpringCloud 和 RPC 的关系

SpringCloud 也是 RPC 框架(Feign + Eureka),反正能远距离调用就是 RPC

20190419174355352.png

什么是微服务

在看什么是微服务之前需要先看下什么是 SOA 架构

软件架构分类

一般把软件架构分成下面几类

单体架构、垂直架构、SOA 架构、微服务架构(MSA)

分布式架构主要使用的就是 SOA 架构(Service Oriented Ambiguity 即面向服务架构)和 微服务架构(MSA)

微服务更像是 SOA 的另一种实现方式,因为 SOA 本质就是把各个模块拆出来的一种思想,网上很多说它们的区别时就像上文的 HTTP 和 RPC 那样,老是把 RPC 的基于 TCP 方式传输直接就当成了 RPC... SOA 因为以前最出名的实现方式就是 ESB(企业服务总线),所以很多文档谈到 SOA 就是特指 ESB,实际上 SOA 也只是一种把各种功能拆开来的思想,ESB 只是一种实现方式,微服务也是其一种实现方式

SOA 架构

面向服务的架构(SOA)是一个组件模型,它将应用程序的不同功能单元(称为服务)进行拆分,并通过这些服务之间定义良好的接口和协议联系起来。

核心思想就是把不同的模块全部拆分出来,用到时调用这个模块

但是,SOA 并没有定义出具体的实现方式

所以目前有两套 SOA 理念的实现方式:中心化和去中心化

中心化

SOA 中心化的实现方式就是 ESB,ESB 通过协议转换、消息解析、消息路由把服务提供者的数据传送到服务消费者。(ESB 企业总线)

去中心化

SOA 去中心化的实现方式就是微服务,目前两个主流的微服务框架就是 Dubbo 和 Spring Cloud

通信方式就是 RPC

示例:商城项目

SpringCloud 是什么

SpringCloud 是一堆服务的集合(就是把各个功能拆成一个个模块,最后像积木一样选择性的拼在一起 ),例如

  • 服务注册与发现
  • 服务调用
  • 服务熔断
  • 负载均衡
  • 服务降级
  • 服务消息队列
  • 配置中心管理
  • 服务网关
  • 服务监控
  • 全链路追踪
  • 自动化部署
  • 服务定时任务调度操作

总而言之就是一个全家桶 image.png

与 SpringBoot 的关系

SpringBoot 专注于快速方便的开发单个个体微服务。 SpringCloud 是关注全局的微服务协调治理架构。 SpringBoot 可以单独使用开发项目、单 SpringCloud 离不开 SpringBoot。

SpringCloud 流程

参考资料 springCloud的流程

image.png

Eureka 注册中心

Eureka 是微服务架构中的注册中心,专门负责服务的注册与发现,就是各个服务都登记在这里,如果某个服务想要调用另一个服务时先检查一下是否有本地缓存,如果没有则询问 Eureka 这个服务的 ip地址(Eureka Server是一个注册中心,里面有一个注册表,保存了各服务所在的机器和端口号),拿到 Eureka 发过来的地址后客户端将这个地址保存到本地缓存里面,下次请求就无需再通过 Eureka 找到这个服务了


Feign 通信工具

Feign 就是实现各个服务之间通信的工具(即 RPC),它的核心就是动态代理模式

  • 首先,如果你对某个接口定义了 @FeignClient 注解,Feign 就会针对这个接口创建一个动态代理
  • 接着你要是调用那个接口,本质就是会调用 Feign 创建的动态代理,这是核心中的核心
  • Feign 的动态代理会根据你在接口上的 @RequestMapping 等注解,来动态构造出你要请求的服务的地址
  • 最后针对这个地址,发起请求、解析响应

Ribbon 负载均衡

就是用来处理负载均衡,例如订单服务可以使用多个服务器来共同面对高并发量,这时就需要使用负载均衡了,合理的把各个请求分摊到各个服务器上,不至于 “一核工作多核围观的” 的情况

分布式系统中,A 服务需要调用 B 服务,B 服务在多台机器中都存在,A 调用任意一个服务器均可完成功能。

为了使每一个服务器都不要太忙或者太闲,我们可以负载均衡的调用每一个服务器,提升网站的健壮性。

常见的负裁均衡算法:

轮询:为第一个请求选择健康池中的第一-个后端服务器,然后按顺序往后依次选择,直到最后一个,然后循环。

最小连接:优先选择连接数最少,也就是压力最小的后端服务器,在会话较长的情况下 可以考虑采取这种方式。

散列:根据请求源的 IP 的散列 (hash)来选择要转发的服务器。这种方式可以一定程度上保证特定用户能连接到相同的服务器。如果你的应用需要处理状态而要求用户能连接到和之前相同的服务器,可以考虑采取这种方式。

Hystrix 熔断器

参考资料 防雪崩利器:熔断器 Hystrix 的原理与使用

在微服务架构里,一个系统会有很多的服务。主要为了防止一个服务挂了,其他的服务调用这个服务一直无法通过,导致雪崩的情况发生

就是:如果使用 Tomcat 的线程池去接收用户的请求(Tomcat 是一个线程一个请求,即大力出奇迹),如果某一个服务出现了故障,这个时候后续有大量的请求过来,那么容器中的线程数量则会持续增加直致 CPU 资源耗尽到 100% (雪崩),导致 Tomcat 无法处理其他业务功能

Hystrix 是隔离、熔断以及降级的一个框架。

隔离:Hystrix 会搞很多个小小的线程池,比如订单服务请求库存服务是一个线程池,请求仓储服务是一个线程池,请求积分服务是一个线程池。每个线程池里的线程就仅仅用于请求那个服务。这样某个服务挂了也只是这个服务的线程池莫得了,其他的线程池还是能正常工作

熔断器:熔断器模式定义了熔断器开关相互转换的逻辑:

image.png

服务的健康状况 = 请求失败数 / 请求总数. 熔断器开关由关闭到打开的状态转换是通过当前服务健康状况和设定阈值比较决定的.

Hystrix的内部处理逻辑:

  • 关闭:当熔断器开关关闭时, 请求被允许通过熔断器. 如果当前健康状况高于设定阈值, 开关继续保持关闭. 如果当前健康状况低于设定阈值, 开关则切换为打开状态.

  • 打开:当熔断器开关打开时, 请求被禁止通过.

  • 半开:当熔断器开关处于打开状态, 经过一段时间后, 熔断器会自动进入半开状态, 这时熔断器只允许一个请求通过. 当该请求调用成功时, 熔断器恢复到关闭状态. 若该请求失败, 熔断器继续保持打开状态, 接下来的请求被禁止通过.

熔断器的开关能保证服务调用者在调用异常服务时, 快速返回结果, 避免大量的同步等待. 并且熔断器能在一段时间后继续侦测请求执行结果, 提供恢复服务调用的可能.

降级:如果某个服务挂了(熔断器判断),Hystrix 还提供降级服务,即调用失败返回的默认数据

Zuul 网关

微服务网关

一般微服务架构中都必然会设计一个网关在里面,像 android、ios、pc 前端、微信小程序、H5 等等,不用去关心后端有几百个服务,就知道有一个网关,所有请求都往网关走,网关会根据请求中的一些特征,将请求转发给后端的各个服务。

而且有一个网关之后,还有很多好处,比如可以做统一的降级、限流、认证授权、安全,等等。

各个模块对应的工具

微服务条目落地实现
服务开发Springboot、Spring、SpringMVC
服务配置与管理Netflix公司的Archaius、阿里的Diamond
服务的注册和发现Eureka、Consul、Zookeeper等
服务的调用Rest、RPC、gRPC
服务熔断器Hystrix、Envoy等
负载均衡Ribbon、Nginx等
服务接口调用(客户端调用服务端的简化工具)Feign等
消息队列Kafaka、RabbitMQ、ActiveMQ等
服务配置中心管理SpringCloudConfig、chef等
服务路由(API网关)Zuul等
服务监控Zabbix、Nagios、Metrics、Spectator等
全链路追踪Zipkin、Brave、Dapper等
服务部署Docker、OpenStack、Kubernetes等
数据量操作开发包SpringCloud Stream(封装与Rdis、Rabbit、Kafaka等收发消息)
事件消息总线SpringCloud Bus

Cloud 升级及替换的工具

image.png

服务注册中心

Eureka:官方停止更新,并且已经有更好的替代产品了,可以使用,但是官方已经不建议使用了(重度患者)。

Zookeeper:某些老系统,以前是用的Zookeeper + Dubbo,后来做技术升级,结果发现SpringCloud的Eureka停更了,然后就用了最少的技术切换,那么就用了Zookeeper做注册中心。

Consul:go语言开发的,也是一个优秀的服务注册框架,但是使用量较少,风头都被 Nacos 抢了。

Nacos:来自于 SpringCloudAlibaba,在企业中经过了百万级注册考验的,不但可以完美替换 Eureka,还能做其他组件的替换,所以强烈建议使用,是学习的重点。

组件名语言CAP服务健康检对外暴露接Spring Cloud 集成
EurekaJavaAP可配支持HTTP已集成
ConsulGoCP支持HTTP/DNS已集成
ZookeeperJavaCP支持客户端已集成

1、满足 CA 舍弃 P,也就是满足一致性和可用性,舍弃容错性。但是这也就意味着你的系统不是分布式的了,因为涉及分布式的想法就是把功能分开,部署到不同的机器上。

2、满足 CP 舍弃 A,也就是满足一致性和容错性,舍弃可用性。如果你的系统允许有段时间的访问失效等问题,这个是可以满足的。就好比多个人并发买票,后台网络出现故障,你买的时候系统就崩溃了。

3、满足 AP 舍弃 C,也就是满足可用性和容错性,舍弃一致性。这也就是意味着你的系统在并发访问的时候可能会出现数据不一致的情况(就是在服务崩了的时候先返回旧值)。

服务调用(负载均衡)

Ribbon:也进入了维护状态,停止更新了,但是 Spring 官方还在使用。

LoadBalancer:Spring 官方推出的一个新的组件,打算逐渐取代掉 Ribbon,但是现在还处于萌芽状态。

服务调用2(通信工具)

Feign:Netflix 公司产品,也停止更新了。

OpenFeign:Spring 社区等不了 Netflix 更新了,然后就自己做了一个组件,不用 Feign 了。

服务降级(熔断器)

Hystrix:官网不推荐使用,但是中国企业中还在大规模使用。

Resilience4J:官网推荐使用,但是国内很少用这个。

Sentienl:来自于 SpringCloudAlibaba,在中国企业替换 Hystrix 的组件,国内强烈建议使用。

服务网关

Zuul:Netflix 公司产品,公司内部产生分歧,有的人想自己出一个Zuul2。

Zuul2:也是 Netflix 公司准备出的产品,但是由于内部分歧,所以 Zuul2 已经胎死腹中了。

gateway:Spring 社区自己出的网关组件,官方隆重介绍和极度推荐的网关服务组件。

服务配置

Config:目前也在使用,风头被 Nacos 抢了。

Nacos:来自于 SpringCloudAlibaba,后来居上,把 Config 给替换了。

服务总线

Bus:SpringCloud 原生的服务总线组件,现在风头也被 Nacos 抢了。

Nacos:来自于 SpringCloudAlibaba,后来居上,把 Bus 给替换了。

SpringBoot 与 SpringCloud 的兼容版本

注意:SpringBoot 和 SpringCloud 有兼容性问题,所以需要选择对应的版本,具体参考 官网 Generating A New Spring Cloud Project

可以看到下面有一句话:Spring Cloud Dalston, Edgware, Finchley, and Greenwich have all reached end of life status and are no longer supported.

说明最低都应该选用 Hoxton 这个版本

也可以通过这个 API 查看

<properties>
<java.version>1.8</java.version>
<spring.cloud-version>Hoxton.SR8</spring.cloud-version>
</properties>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring.cloud-version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

Reference

Spring 官网 Spring cloud 中文文档 Spring cloud 中文文档-各个模块 参考资料 如何给老婆解释什么是RPC -- 柳树 参考资料 SOA、ESB、微服务的关系梳理 参考资料 既然有 HTTP 请求,为什么还要用 RPC 调用? 参考资料 RPC和RESTful API入门篇 参考资料 springCloud的流程 参考资料 隔离技术线程池(ThreadPool)和信号量(semaphore) 学习资料 2020年 最新版 SpringCloud教程